using System;
using System.Threading;

namespace XTCast.Mp3 {
	
	public class Throttle
	{

		private DateTime target;
		private TimeSpan slipThreshold;
		private TimeSpan maxSlip = TimeSpan.MaxValue;
		private TimeSpan maxAhead = TimeSpan.MaxValue;
		
		public Throttle()
		{
			Reset();
		}

		public Throttle(DateTime startTarget, TimeSpan slipThreshold, TimeSpan maxSlip, TimeSpan maxAhead) 
		{
			target = startTarget;
			this.slipThreshold = slipThreshold;
			this.maxSlip = maxSlip;
			this.maxAhead = maxAhead;
		}

		public Throttle(DateTime startTarget,TimeSpan slipThreshold ) 
		{
			target = startTarget;
			this.slipThreshold = slipThreshold;
		}
		
		public bool IsAhead 
		{
			get { return Ahead>TimeSpan.Zero; }
		}

		public bool IsSlipping
		{
			get { return Slip>=slipThreshold; }
		}

		public virtual TimeSpan Slip
		{
			get 
			{
				TimeSpan slip = DateTime.Now.Subtract(target);
				if (slip>maxSlip) 
					return maxSlip;
				else
					return slip;
			}
		}

		public virtual TimeSpan Ahead
		{
			get 
			{
				return target.Subtract(DateTime.Now);
			}
		}

		public virtual void Add(TimeSpan add, bool sleepWhileAhead)
		{
			TimeSpan slip = DateTime.Now.Subtract(target+add);
			if (slip>maxSlip)
				target=DateTime.Now-maxSlip;
			else 
			{
				if (-slip>maxAhead)
					target=DateTime.Now+maxAhead;
				else
					target+=add;
			}
			if (sleepWhileAhead) {
				TimeSpan ahead = Ahead;
				if (ahead>TimeSpan.Zero)
					System.Threading.Thread.Sleep(ahead);
			}
		}
		
		public virtual void Reset()
		{
			target = System.DateTime.Now;
		}

		public virtual void Reset(TimeSpan ts) {
			target = System.DateTime.Now+ts;
		}
	}
}